package com.example.chatroom.controller;

import com.example.chatroom.common.component.OnlineUserManager;
import com.example.chatroom.common.errorcode.ServiceErrorCodeConstants;
import com.example.chatroom.common.exception.ControllerException;
import com.example.chatroom.common.exception.ServiceException;
import com.example.chatroom.common.utils.JacksonUtil;
import com.example.chatroom.controller.param.WebSocketMessageParam;
import com.example.chatroom.controller.result.WebSocketMessageResult;
import com.example.chatroom.dao.dataobject.FriendInfoDO;
import com.example.chatroom.dao.dataobject.MessageDO;
import com.example.chatroom.dao.mapper.MessageMapper;
import com.example.chatroom.dao.mapper.MessageSessionUserMapper;
import com.example.chatroom.dao.mapper.UserMapper;
import com.example.chatroom.service.dto.UserDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.util.List;

@Component
@Slf4j
public class WebSocketMessage extends TextWebSocketHandler {
    @Autowired
    private MessageSessionUserMapper messageSessionUserMapper;
    @Autowired
    private OnlineUserManager onlineUserManager;
    @Autowired
    private MessageMapper messageMapper;
    @Autowired
    private UserMapper userMapper;

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        log.info("WebSocketMessage 服务端连接成功");
        Long userId = (Long)session.getAttributes().get("userId");
        if(userId==null){
            log.info("Httpsession userId:{}", userId);
            return;
        }
        if(onlineUserManager.onlineUser(userId,session)==false){
            log.error(ServiceErrorCodeConstants.WEBSOCKET_ONLINE_ERROR.getMsg());
            throw new ServiceException(ServiceErrorCodeConstants.WEBSOCKET_ONLINE_ERROR);
        }
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        log.info("WebSocketMessage 服务端收到消息 message:{}",message.toString());
        //1-    获取当前登陆用户Id（发送信息者）
        Long userId = (Long)session.getAttributes().get("userId");
        if(userId==null){
            log.info("Httpsession userId:{}", userId);
            return;
        }

        //2-    将信息插入到message表中
        //从前端的负载message中获取sessionId
        WebSocketMessageParam webSocketMessageParam = JacksonUtil.readValue(message.getPayload(), WebSocketMessageParam.class);
        log.info("message:"+JacksonUtil.writeValueAsString(webSocketMessageParam));

        if(webSocketMessageParam.getType().equals("message")){
            //3-    消息转发
            transferMessage(userId,webSocketMessageParam);
        }else{
            log.info("message type:{}",webSocketMessageParam.getType());
            return;
        }

    }

    /**
     * 处理消息转发逻辑
     * @param userId 当前登陆用户
     * @param webSocketMessageParam 前端负载信息
     */
    private void transferMessage(Long userId, WebSocketMessageParam webSocketMessageParam) {
        //1-    将信息存储到数据库中
        Long sessionId = webSocketMessageParam.getSessionId();
        String content = webSocketMessageParam.getContent();
        MessageDO messageDO=new MessageDO();
        //发送者
        messageDO.setFormId(userId);
        //会话
        messageDO.setSessionId(sessionId);
        messageDO.setContent(content);
        messageMapper.insertSelective(messageDO);

        //2-    构造响应信息WebSocketMessageResult
        WebSocketMessageResult webSocketMessageResult=new WebSocketMessageResult();
        webSocketMessageResult.setType("message");
        webSocketMessageResult.setFromId(userId);
        webSocketMessageResult.setFromName(userMapper.selectByPrimaryKey(userId).getUserName());
        webSocketMessageResult.setSessionId(sessionId);
        webSocketMessageResult.setContent(content);
        webSocketMessageResult.setPostTime(messageMapper.selectByFSC(userId,sessionId,content));
        //将java对象-> JSON字符串
        String s = JacksonUtil.writeValueAsString(webSocketMessageResult);

        //3-    查询响应发送的客户端websocketSession
        List<FriendInfoDO> friendInfoDOS = messageSessionUserMapper.selectBySessionId(sessionId, userId);
        //  需要给自己发，所以将自己添加进去
        FriendInfoDO friendInfo=new FriendInfoDO();
        friendInfo.setFriendName(userMapper.selectByPrimaryKey(userId).getUserName());
        friendInfo.setFriendId(userId);
        friendInfoDOS.add(friendInfo);
        // 群聊
        friendInfoDOS.forEach(friendInfoDO -> {
            //4-    获取session，并转发信息
            WebSocketSession webSocketSession = onlineUserManager.getWebSocketSession(friendInfoDO.getFriendId());
            if(webSocketSession==null){
                //当前用户下线 不用发送
            }else{
                try {
                    webSocketSession.sendMessage(new TextMessage(s));
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        });
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        log.info("WebSocketMessage 服务端连接异常 exception:{}",exception);
        Long userId = (Long)session.getAttributes().get("userId");
        if(userId==null){
            log.info("Httpsession userId:{}", userId);
            return;
        }
        if(onlineUserManager.offLine(userId,session)==false){
            log.error(ServiceErrorCodeConstants.WEBSOCKET_OFFLINE_ERROR.getMsg());
            throw new ServiceException(ServiceErrorCodeConstants.WEBSOCKET_OFFLINE_ERROR);
        }
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
       log.info("WebSocketMessage 服务端断开连接 status:{}",status);
        Long userId = (Long)session.getAttributes().get("userId");
        if(userId==null){
            log.info("Httpsession userId:{}", userId);
            return;
        }
        if(onlineUserManager.offLine(userId,session)==false){
            log.error(ServiceErrorCodeConstants.WEBSOCKET_OFFLINE_ERROR.getMsg());
            throw new ServiceException(ServiceErrorCodeConstants.WEBSOCKET_OFFLINE_ERROR);
        }
    }
}
